﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Linq;
using System.Transactions;
using yiCommerce.Core;
using yiCommerce.Core.Data;
using yiCommerce.Core.Domain.Customers;
using yiCommerce.Core.Domain.FriendShips;
using yiCommerce.Core.Domain.Pictures;
using yiCommerce.Core.Domain.Products;
using yiCommerce.Core.Domain.Statuses;
using yiCommerce.Core.Domain.Tags;
using yiCommerce.Data.Respository;
using yiCommerce.Service.Customers;
using yiCommerce.Service.Orders;
using yiCommerce.Service.Tags;

namespace yiCommerce.Service.Statuses
{
    public class StatusService:IStatusService
    {
        private IRepository<Comment> _commentRep;
        private IRepository<Status> _statusRep;
        private IRepository<Tag> _tagRep;
        private IRepository<FriendShip> _friendShipRep;

        private ITagService _tagService;
        private IRepository<StatusTag> _statusTagRep;
        private IStatusesRepository _statusesRep;
        private IRepository<Customer> _customerRep;
        private IRepository<StatusPointDetail> _statusPointRep;


        public StatusService(IRepository<Status> statusRep, IRepository<FriendShip> friendShipRep, IRepository<Comment> commentRep, ITagService tagService, IRepository<StatusTag> statusTagRep, IRepository<Tag> tagRep, IStatusesRepository statusesRep, IRepository<Customer> customerRep, IRepository<StatusPointDetail> statusPointRep)
        {
            _statusRep = statusRep;
            _friendShipRep = friendShipRep;
            _commentRep = commentRep;
            _tagService = tagService;
            _statusTagRep = statusTagRep;
            _tagRep = tagRep;
            _statusesRep = statusesRep;
            _customerRep = customerRep;
            _statusPointRep = statusPointRep;
        }

        


        public Status Update(string text, int customerId, IList<int> pictureIds, bool isProudct, int? productId, IList<string> tags  )
        {

            var status = new Status()
                {
                    CreatedAt = DateTime.Now,
                    CustomerId = customerId,
                    Deleted = false,
                    Text = text,
                    IsProductStatus = isProudct
                    //StatusPictures = new Collection<StatusPicture>()
                    //    {
                            
                    //    }
                };

            if (isProudct)
            {
                status.ProductId = productId.Value;
            }

            _statusRep.Insert(status);


            if (pictureIds != null)
            {
                
                status.StatusPictures = pictureIds.Select((picId, index) => new StatusPicture()
                {
                    DisplayOrder = index + 1,
                    PictureId = picId,
                    StatusId = status.Id,
                }).ToList();

                _statusRep.Update(status);
            }

            if (tags != null)
            {
                foreach (var tag in tags)
                {
                    var tagId = _tagService.AddTag(tag, tag, customerId);

                    var st = new StatusTag()
                    {
                        StatusId = status.Id,
                        TagId = tagId
                    };

                    _statusTagRep.Insert(st);
                }
            }

            
            return this.GetById(status.Id);
        }

        private Status GetById(int id)
        {
            var query = from s in _statusRep.Table
                        where s.Id ==id 
                              && s.Deleted == false
                        select s;
            var p = query.SingleOrDefault();
            if (p != null)
            {
                return StatusMapper.ToStatusModel(p,false);
            }
            else
            {
                return null;
            }
        }

        public IList<Status> UserTimeLine(int customerId, int pageIndex, int pageSize)
        {
            var query = from s in _statusRep.Table
                        where s.CustomerId == customerId
                              && s.Deleted == false
                              orderby s.CreatedAt descending 
                        select s;
            var tempResult = new PagedList<Status>(query, pageIndex, pageSize);
             return StatusMapper.ToStatusesList(tempResult.ToList());
           
        }

        public IList<Status> HomeTimeLine(int customerId,int pageIndex, int pageSize)
        {


            var status = (from s in _statusRep.Table
                          where s.CustomerId == customerId
                                && s.Deleted == false
                          select s).Union(

                              from f in _friendShipRep.Table
                              join s in _statusRep.Table
                                  on f.FriendId equals s.CustomerId
                              where f.OwnerId == customerId && s.Deleted == false
                              select s);



             status =  status.OrderByDescending(c => c.CreatedAt);


            var tempResult = new PagedList<Status>(status, pageIndex, pageSize);

            return StatusMapper.ToStatusesList(tempResult.ToList());
            
        }

        public IList<Status> HomeTimeLineProduct(int customerId, int pageIndex, int pageSize)
        {

            var status = (from s in _statusRep.Table
                          where s.CustomerId == customerId
                          && s.IsProductStatus==true
                                && s.Deleted == false
                          select s).Union(

                              from f in _friendShipRep.Table
                              join s in _statusRep.Table
                                  on f.FriendId equals s.CustomerId
                              where f.OwnerId == customerId && s.Deleted == false
                                && s.IsProductStatus==true
                              select s);


            status = status.OrderByDescending(c => c.CreatedAt);


            var tempResult = new PagedList<Status>(status, pageIndex, pageSize);

            return StatusMapper.ToStatusesList(tempResult.ToList());
        }

        public Status GetStatusById(int statusId , bool autoLoadComments=false)
        {
           

            var statusQuery = from s in _statusRep.Table
                              where s.Id == statusId
                              select s;

            var status = statusQuery.SingleOrDefault();

            if (status != null)
            {

               
                return StatusMapper.ToStatusModel(status, autoLoadComments);
            }
            else
            {
                return null;
            }
        }

        public IPagedList<Status> FindStatusByTag(string tagName, int pageIndex, int pageSize)
        {
            var query = from c in _tagRep.Table
                        from st in c.StatusTag
                        where c.TagName == tagName
                        orderby st.Status.CreatedAt descending
                        select st.Status;


            var tempResult = new PagedList<Status>(query, pageIndex, pageSize);

            var list = tempResult.Select(c =>StatusMapper.ToStatusModel(c, false)).ToList();

            var pagedList = new PagedList<Status>(list, pageIndex, pageSize, query.Count());
            return pagedList;
        }

        public void GivePointToStatuses(int statusId, int customerId, int point = 1)
        {
            using (var scope = new TransactionScope())
            {

                _statusesRep.GivePointToStatuses(statusId, customerId, point);


                var pointDetail = new StatusPointDetail()
                    {
                        Customer = _customerRep.GetById(customerId),
                        CreatedAt = DateTime.Now,
                        Point = point,
                        Status = _statusRep.GetById(statusId)
                    };
                _statusPointRep.Insert(pointDetail);
                scope.Complete();

            }
        }

        public int? GetPointOfStatus(int statusId)
        {
            var query = from s in _statusRep.Table where s.Id == statusId select s.Point;
            return query.SingleOrDefault();

        }
    }
}